#ifndef _BUOLA_CV_FEATURES_CMATCHER_H
#define _BUOLA_CV_FEATURES_CMATCHER_H

#include <buola/cv/features/cfeaturematches.h>
#include <buola/cv/features/cfeatureset.h>

namespace buola { namespace cvi {

template<typename tMatcher>
class CMatcher
{
public:
    template<typename... tArgs>
    CMatcher(tArgs&&... pArgs)
        :   mMatcher(std::forward<tArgs>(pArgs)...)
    {}
    
    std::vector<CMatch> Match(const mat::CMat_f &pQuery,const mat::CMat_f &pTrain);

private:
    tMatcher mMatcher;
};

static std::vector<CMatch> convert_matches(const std::vector<cv::DMatch> &pMatches)
{
    std::vector<CMatch> lReturn;
    lReturn.reserve(pMatches.size());
    
    for(const cv::DMatch &m : pMatches)
        lReturn.emplace_back(m);
    
    return lReturn;
}

template<typename tMatcher>
std::vector<CMatch> CMatcher<tMatcher>::Match(const mat::CMat_f &p1,const mat::CMat_f &p2)
{
    std::vector<cv::DMatch> lMatches;
    
    mMatcher.match(mat_wrap(p1),mat_wrap(p2),lMatches);
    
    return convert_matches(lMatches);
}

typedef CMatcher<cv::BFMatcher> CBFMatcher;

CFeatureMatches bf_match(const CFeatureSet &p1,const CFeatureSet &p2)
{
    CBFMatcher lMatcher(cv::NORM_L2,true);
    std::vector<CMatch> lMatches=lMatcher.Match(p1.Features(),p2.Features());
    
    return CFeatureMatches(p1,p2,std::move(lMatches));
}

/*namespace cvi*/ } /*namespace buola*/ }

#endif
